package se.webbzon.boltzmann.editor.component.sequence;

import java.awt.BorderLayout;
import java.awt.Dimension;

import javax.swing.JPanel;

import se.webbzon.boltzmann.editor.component.AbstractComponent;
import se.webbzon.boltzmann.editor.component.sequence.factory.DefaultSequenceRowFactoryGroup;
import se.webbzon.boltzmann.editor.component.sequence.panel.factory.DefaultRowPanelFactoryGroup;
import se.webbzon.boltzmann.editor.mvc.EditorModel;
import se.webbzon.boltzmann.factory.AbstractFactoryException;
import se.webbzon.boltzmann.game.sequence.builder.AbstractSequenceRow;
import se.webbzon.boltzmann.game.sequence.builder.SequenceBuilder;

public class SequenceBuilderPanel extends AbstractComponent {
	
	// Auto generated serial version UID
	private static final long serialVersionUID = 1183857769076227701L;

	// The sequence builder associated with this panel
	private final SequenceBuilder builder;
	
	// The row panel of this sequence builder panel
	private final RowPanel rowPanel;
	
	// The row editor panel of this sequence builder panel
	private final RowEditPanel editPanel;
	
	// The generic row panel of this sequence builder panel
	private final GenericRowPanel genericPanel;
	
	/*============================================================
	Constructors
	============================================================*/
	
	/** Creates a new sequence builder panel. **/
	public SequenceBuilderPanel(EditorModel model, SequenceBuilder builder) {
		super("Sequence");
		this.builder = builder;
		setLayout(new BorderLayout());
		
		BuilderListener builderListener = new BuilderListener();
		EditorListener editListener = new EditorListener();
		
		// Create the builder panel (the left-side panel)
		JPanel builderPanel = new JPanel();
		builderPanel.setLayout(new BorderLayout());
		
		try {
			RowFactoryPanel rowFactoryPanel = 
					new RowFactoryPanel(builder,
										new DefaultSequenceRowFactoryGroup());
			rowFactoryPanel.addListener(builderListener);
			builderPanel.add(rowFactoryPanel,BorderLayout.NORTH);
		} catch (AbstractFactoryException e) {
			e.printStackTrace();
		}
		
		
		rowPanel = new RowPanel(builder);
		rowPanel.setPreferredSize(new Dimension(-1,256));
		rowPanel.addListener(builderListener);
		builderPanel.add(rowPanel,BorderLayout.CENTER);
		
		add(builderPanel,BorderLayout.WEST);
		
		// Create the edit panel (the right-side panel)
		JPanel centerPanel = new JPanel();
		centerPanel.setLayout(new BorderLayout());
		
		editPanel = new RowEditPanel(model,builder);
		editPanel.addListener(editListener);
		centerPanel.add(editPanel,BorderLayout.CENTER);
		
		// Create row generic panel
		GenericRowPanel genericPanel = null;
		try {
			genericPanel = new GenericRowPanel(new DefaultRowPanelFactoryGroup());
			genericPanel.addListener(editListener);
			centerPanel.add(genericPanel,BorderLayout.SOUTH);
		} catch (AbstractFactoryException e) {
			e.printStackTrace();
		} finally {
			this.genericPanel = genericPanel;
		}
		
		add(centerPanel,BorderLayout.CENTER);
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	/** A listener used to listen to the builder panel. **/
	private final class BuilderListener implements RowListener, RowFactoryListener {

		@Override public void addRow(RowFactoryPanel source, AbstractSequenceRow row) {
			rowPanel.addRow(row);
			rowPanel.selectRow(row);
		}

		@Override public void insertRow(RowFactoryPanel source, AbstractSequenceRow row) {
			int index = rowPanel.getSelectedIndex();
			if (index >= 0)
				rowPanel.insertRow(row, index);
			else
				rowPanel.addRow(row);
			builder.moveRow(builder.rows()-1, index);
			rowPanel.selectRow(row);
		}

		@Override public void selectRow(RowPanel source, AbstractSequenceRow row) {
			if (row != null) {
				editPanel.editRow(row);
				genericPanel.editRow(row);
			}
		}

		@Override public void removeRow(RowPanel source, AbstractSequenceRow row) {
			if (row != null) {
				builder.removeRow(row);
				editPanel.editRow(null);
				genericPanel.editRow(null);
			}
		}
		
	}
	
	/** A listener used to listen to the editor panel. **/
	private final class EditorListener implements RowEditListener, GenericRowListener {

		@Override public void editRow(RowEditPanel source, AbstractSequenceRow row) {
			if (rowPanel.getSelectedValue() != row && row != null) {
				rowPanel.selectRow(row);
				genericPanel.editRow(row);
			}
		}

		@Override public void changeRow(RowEditPanel source, AbstractSequenceRow row) {
			rowPanel.repaint();
			genericPanel.repaint();
		}

		@Override public void editRow(GenericRowPanel source, AbstractSequenceRow row) {
			if (rowPanel.getSelectedValue() != row && row != null) {
				rowPanel.selectRow(row);
				editPanel.editRow(row);
			}
		}

		@Override public void changeRow(GenericRowPanel source, AbstractSequenceRow row) {
			rowPanel.repaint();
			editPanel.repaint();
		}
		
	}

}
